#include <iostream>

#include "SDL/SDL_thread.h"

#include "EventLoop.h"


using namespace std;


/*
 * Overly complicated way to handle quit events.
 */
// TODO: make sure this mechanism is threadsafe.
class Quit
{
private:
	static bool quit;

public:
	static bool isQuitting()
	{
		return Quit::quit;
	}

	/*
	 * Trigger a quit event in a threadsafe way.
 	*/
	static void triggerQuit()
	{
		cout << "In Quit::triggerQuit(): SDL_QuitRequested = " << SDL_QuitRequested() << ", quit = " << Quit::quit << endl;
		if(!Quit::quit)
		{
			Quit::quit = true;

			// Push a quit event onto the event queue.
			SDL_Event event;
			event.type = SDL_QUIT;
			SDL_PushEvent(&event);
		}
	}
};


bool Quit::quit = false;


/*
 * This function lets us filter events before they are
 * put in the event queue. NB: Runs in a separate thread.
 * Enable in main() if it is to be used.
 */
/*
int filterEvents(const SDL_Event * event)
{
	switch(event->type)
	{
	case SDL_QUIT:
		// cout << "Got a quit event, could've filtered it out here." << endl;
		// return 0;
	}
	return 1;
}
*/

/*
 * This is the loop that handles all kinds of system
 * events and passes them to the appropriate threads.
 */
void eventLoop()
{
	SDL_Event event;
	while( SDL_WaitEvent(&event) >= 0 )
	{
		switch(event.type)
		{
		// Keyboard events
		case SDL_KEYDOWN:
		case SDL_KEYUP:
		{
			bool down = event.key.type == SDL_KEYDOWN;
			bool shift = event.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT);
			bool ctrl  = event.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL);
			bool alt   = event.key.keysym.mod & (KMOD_LALT | KMOD_RALT);
			switch(event.key.keysym.sym)
			{
			case SDLK_LEFT:
				break;
			case SDLK_RIGHT:
				break;
			case SDLK_UP:
				break;
			case SDLK_DOWN:
				break;

			case SDLK_PAGEUP:
				break;
			case SDLK_PAGEDOWN:
				break;

			case SDLK_SPACE:
				break;
			case SDLK_RETURN:
				break;

			case SDLK_ESCAPE:
				Quit::triggerQuit();
				break;
			default:
				cout << "Not handled key: " << SDL_GetKeyName(event.key.keysym.sym) << endl;
				break;
			}
			break;
		}

		// Mouse events
		case SDL_MOUSEMOTION:
		{
			int x = event.motion.x;
			int y = event.motion.y;
			int xrel = event.motion.xrel;
			int yrel = event.motion.yrel;
			break;
		}
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
		{
			bool down = event.button.type == SDL_MOUSEBUTTONDOWN;
			int x = event.button.x;
			int y = event.button.y;
			int button = event.button.button;

			break;
		}

		// System events
		case SDL_QUIT:
			if(!Quit::isQuitting())
			{
				cerr << "Got SDL_QUIT event without the invocation of Quit::triggerQuit?" << endl;
			}
			// Return control to main thread, which should shut
			// down all the threads in an orderly fashion.
			return;
		case SDL_ACTIVEEVENT:
			if(event.active.state & SDL_APPACTIVE)
			{
				if(event.active.gain)
				{
					cout << "App activated." << endl;
				}
				else
				{
					cout << "App deactivated." << endl;
				}
			}
			break;
		case SDL_USEREVENT:
			cout << "swapping" << endl;
			SDL_GL_SwapBuffers();
			// TODO: signal condition variable to continue drawing
			//SDL_CondSignal(drawcond);
			break;
		}
	}
}
